#include "StdAfx.h"
#include <stdio.h>
CGraphics::CGraphics(void)
{
}

CGraphics::~CGraphics(void)
{
		// Set the back buffer to it's original bitmap (This is necessary for clean-up)
	SelectObject(_hdcBack, _hOldBitmap);

	// Free the hbitmaps
	if(_hOldBitmap)	DeleteObject(_hOldBitmap);
	if(_hCompBitmap)	DeleteObject(_hCompBitmap);

	// Free all the HDC's
	if(_hdcBack)		ReleaseDC(_hWnd, _hdcBack);
	if(_hdcBitmap)	ReleaseDC(_hWnd, _hdcBitmap);
	if(_hdcFront)	ReleaseDC(_hWnd, _hdcFront);

}

void CGraphics::CreateDoubleBuffering(HWND hWnd)
{
	this->_hWnd = hWnd;
	GetClientRect(_hWnd, &_scrnRect);
	this->_hdcFront = GetDC(_hWnd);
	this->_hdcBack = CreateCompatibleDC(_hdcFront);
	this->_hdcBitmap = CreateCompatibleDC(_hdcFront);
	this->_hCompBitmap = CreateCompatibleBitmap(_hdcFront, _scrnRect.right, _scrnRect.bottom);
	this->_hOldBitmap = (HBITMAP)SelectObject(_hdcBack, _hCompBitmap);
}

void CGraphics::FlipBuffers(BOOL clearScreen)
{
	BitBlt(_hdcFront, _scrnRect.left, _scrnRect.top, _scrnRect.right, _scrnRect.bottom, _hdcBack, 0, 0, SRCCOPY);

	// TODO: write a method to clear the screen...

}

void CGraphics::DisplayBitmap(HBITMAP hBitmap, int x, int y)
{
	// Select the bitmap handle into the extra hdc that holds the bitmap
	HBITMAP hOldBitmap = (HBITMAP) SelectObject(_hdcBitmap, hBitmap);

	// Blit the bitmap hdc into the backbuffer
	BitBlt(_hdcBack, x, y, _scrnRect.right, 
		   _scrnRect.bottom,  _hdcBitmap, 0, 0, SRCCOPY);

	// Select the old handle to the bitmap back where it was to clean up
	SelectObject(_hdcBitmap, hOldBitmap);
}

HBITMAP CGraphics::LoadBitmapFromResource(int resourceID, HINSTANCE hInstance)
{
	return (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(resourceID),IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR);
}

void CGraphics::ClearPortionOfScreen(int color, RECT portion)
{
	FillRect(this->_hdcBack, &portion, (HBRUSH)GetStockObject(color));
}

void CGraphics::DisplayText(LPCWSTR szText, RECT *pRect, UINT flags)
{
	int nLength = wcslen(szText);
	SetTextColor(_hdcBack,RGB(0,0,0));
	SetBkMode(_hdcBack, TRANSPARENT);

	DrawText(_hdcBack, szText, nLength,pRect, flags);
}

void CGraphics::TransparentBlit(HDC hdc, int destX, int destY, int destWidth, int destHeight, HDC hdc2, int srcX, int srcY, UINT transparency)						      
{

	unsigned char* pImageBits = NULL;
	unsigned char* pBackBits = NULL;
	BITMAPINFO bmBitmapInfo = {0};
	HBITMAP hBitmap, hBitmap2, hOldBitmap, hOldBitmap2;
	HDC compHDC;
	HDC compHDC2;
	
	// Fill in our BitmapInfo structure (we want a 24 bit image)
	bmBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmBitmapInfo.bmiHeader.biCompression = BI_RGB;
	bmBitmapInfo.bmiHeader.biHeight = destHeight;
	bmBitmapInfo.bmiHeader.biWidth = destWidth;	
	bmBitmapInfo.bmiHeader.biBitCount = 24;
	bmBitmapInfo.bmiHeader.biClrUsed = 0;
	bmBitmapInfo.bmiHeader.biPlanes = 1;

	// Create 2 DIB Sections.  One for the Front Buffer and one for the BackBuffer
	hBitmap  = CreateDIBSection(hdc,  &bmBitmapInfo, DIB_RGB_COLORS,(void **)&pImageBits, 0,0);	
	hBitmap2  = CreateDIBSection(hdc,  &bmBitmapInfo, DIB_RGB_COLORS,(void **)&pBackBits, 0,0);

	// Create a compatible DC for the front buffer and Select our Dib Section into it
	compHDC = CreateCompatibleDC(hdc);
	hOldBitmap = (HBITMAP)SelectObject(compHDC, hBitmap);
	
	// Create a compatible DC for the back buffer and Select our Dib Section into it
	compHDC2 = CreateCompatibleDC(hdc2);
	hOldBitmap2 = (HBITMAP)SelectObject(compHDC2, hBitmap2);

	// Blit the front buffer to our compatible DC that will hold the destination bits
	BitBlt(compHDC, 0, 0, destWidth, destHeight, hdc, destX, destY, SRCCOPY);

	// Blit the back buffer to our compatible DC that will hold the source bits
	BitBlt(compHDC2, 0, 0, destWidth, destHeight, hdc2, srcX, srcY, SRCCOPY);

	// Loop through the 24 bit image (Times 3 for R G and B)
	for(int i = 0; i < destHeight * destWidth * 3; i += 3)
	{
		// Check if the current pixel being examined isn't the transparent color
		// Remember, the image bits are stored (Blue, Green, Red), not (Red, Green, Blue)
		// We use the system macros to abstract the R G B data
		if((pBackBits[i]   != GetBValue(transparency)) || 
		   (pBackBits[i+1] != GetGValue(transparency)) || 
		   (pBackBits[i+2] != GetRValue(transparency)))
		{
			// Assign the desired pixel to the foreground
			pImageBits[i]     = pBackBits[i];
			pImageBits[i + 1] = pBackBits[i + 1];
			pImageBits[i + 2] = pBackBits[i + 2];
		}
	}  

	// Blit the transparent image to the front buffer (Voila!)
	BitBlt(hdc, destX, destY, destWidth, destHeight, compHDC, 0, 0, SRCCOPY);

	// Cleanup the monochrome bitmaps
	SelectObject(compHDC, hOldBitmap);
	SelectObject(compHDC2, hOldBitmap2);	

	// Free GDI Resources
	DeleteObject(hBitmap);
	DeleteObject(hBitmap2);
	DeleteDC(compHDC);
	DeleteDC(compHDC2);


}

void CGraphics::DisplayTransparentBitmap(HBITMAP hBitmap, int x, int y, UINT transparentColor)
{
		// Select the bitmap handle into the extra hdc that holds the bitmap
	HBITMAP hOldBitmap = (HBITMAP) SelectObject(_hdcBitmap, hBitmap);

	// Blit the bitmap hdc into the backbuffer using the transparent
	TransparentBlit(_hdcBack, x, y, _scrnRect.right, 
					_scrnRect.bottom, _hdcBitmap, 0, 0, transparentColor);

	// Select the old handle to the bitmap back where it was to clean up
	SelectObject(_hdcBitmap, hOldBitmap);
}